import { authenticate, Info } from '@/store/modules/account/info';
import { Route } from '@/router/index';
import { union } from 'lodash';
import { notEmpty } from '@/utils/General';
import { DataObject } from '@/utils/types';
import { ElMessage } from 'element-plus';

// export const hasAuthority = (route: Route, info: Info): boolean => {
//   if (route.meta && route.meta.authorities) {
//     return authenticate(route.meta.authorities, info.authorities);
//   } else {
//     return true;
//   }
// };

// export const filter = (routes: Route[], info: Info): Route[] => {
//   const res: Route[] = [];
//   routes.forEach(route => {
//     const tmp = { ...route };
//     if (hasAuthority(tmp, info)) {
//       if (tmp.children) {
//         tmp.children = filter(tmp.children, info);
//       }
//       res.push(tmp);
//     }
//   });
//   return res;
// };

// export const hasAuthority = async (
//   route: Route,
//   info: Info,
//   parent: string[]
// ): Promise<string[]> => {
//   if (route.meta && route.meta.authorities) {
//     const authorities = union(parent, route.meta.authorities);
//     // console.log(
//     //   `local authenticate: ${route.path}`,
//     //   authorities,
//     //   info.authorities
//     // );
//     if (authenticate(authorities, info.authorities)) {
//       return authorities;
//     } else {
//       throw new Error(`local authenticate: ${route.path} failed`);
//     }
//   } else {
//     const resp = await accessResourceService.searchPathAuthority(route.path);
//     const authorities = union(parent, HttpUtil.getData(resp));
//     // console.log(
//     //   `remote authenticate: ${route.path}`,
//     //   authorities,
//     //   info.authorities
//     // );
//     if (authenticate(authorities, info.authorities)) {
//       return authorities;
//     } else {
//       throw new Error(`remote authenticate: ${route.path} failed`);
//     }
//   }
// };
//
// export const filter = async (
//   routes: Route[],
//   info: Info,
//   parent?: string[]
// ): Promise<Route[]> => {
//   const result: Route[] = [];
//   for (const item of routes) {
//     const route = { ...item };
//     try {
//       const authorities = await hasAuthority(route, info, parent ?? []);
//       if (route.children) {
//         route.children = await filter(route.children, info, authorities);
//         if (notEmpty(route.children)) {
//           result.push(route);
//         }
//       } else {
//         result.push(route);
//       }
//     } catch (e) {
//       console.log(e.message);
//     }
//   }
//   return result;
// };

export const getPaths = (routes: Route[]): string[] => {
  let result: string[] = [];
  for (const route of routes) {
    if (route.children) {
      const children = getPaths(route.children);
      if (notEmpty(children)) {
        result = result.concat(children);
      }
    } else {
      result.push(route.path);
    }
  }
  return result;
};

export const hasAuthority = async (
  route: Route,
  info: Info,
  parent: string[],
  pathAuthorities: DataObject<string[]>
): Promise<string[]> => {
  if (route.meta && route.meta.authorities) {
    const authorities = union(parent, route.meta.authorities);
    // console.log(
    //   `local authenticate: ${route.path}`,
    //   authorities,
    //   info.authorities
    // );
    if (authenticate(authorities, info.authorities)) {
      return authorities;
    } else {
      throw new Error(`local authenticate: ${route.path} failed`);
    }
  } else {
    const authorities = union(parent, pathAuthorities[route.path]);
    // console.log(
    //   `remote authenticate: ${route.path}`,
    //   authorities,
    //   info.authorities
    // );
    if (authenticate(authorities, info.authorities)) {
      return authorities;
    } else {
      throw new Error(`remote authenticate: ${route.path} failed`);
    }
  }
};

export const filter = async (
  routes: Route[],
  info: Info,
  parent: string[],
  pathAuthorities: DataObject<string[]>
): Promise<Route[]> => {
  const result: Route[] = [];
  for (const item of routes) {
    const route = { ...item };
    try {
      const authorities = await hasAuthority(route, info, parent, pathAuthorities);
      if (route.children) {
        route.children = await filter(route.children, info, authorities, pathAuthorities);
        if (notEmpty(route.children)) {
          result.push(route);
        }
      } else {
        result.push(route);
      }
    } catch (e) {
      ElMessage.error((e as Error).message);
    }
  }
  return result;
};

export const mergeRoutes = (constantRoutes: Route[], errorRoutes: Route[], asyncRoutes?: Route[]): Route[] => {
  if (asyncRoutes && asyncRoutes.length > 0) {
    let result: Route[] = [...constantRoutes];
    asyncRoutes.forEach(asyncRoute => {
      const constantRoute = result.find(route => route.name === asyncRoute.name);
      if (constantRoute) {
        const constantRouteChildren: Route[] | undefined = constantRoute.children;
        if (constantRouteChildren && constantRouteChildren.length > 0) {
          const asyncChildren: Route[] | undefined = asyncRoute.children;
          if (asyncChildren && asyncChildren.length > 0) {
            const temp = { ...asyncRoute };
            temp.children = [...constantRouteChildren, ...asyncChildren];
            result = [...result, temp];
          } else {
            const temp = { ...asyncRoute };
            result = [...result, temp];
          }
        } else {
          const temp = { ...asyncRoute };
          result = [...result, temp];
        }
      } else {
        const temp = { ...asyncRoute };
        result = [...result, temp];
      }
    });
    return [...result, ...errorRoutes];
  }
  return [...constantRoutes, ...errorRoutes];
};
